package com.john.study.es.fetcher;

import com.john.common.util.PatternUtil;
import com.john.study.es.config.matcher.PatternMatcher;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author jiangguangtao 2017/7/28.
 */
public class FetchContext {
    private static final Logger LOGGER = LoggerFactory.getLogger(FetchContext.class);

    private static final ReentrantLock LOCK = new ReentrantLock();
    private String url;
    private boolean fetchUrls = true; // 是否获取页面中的链接
    private Queue<String> urlList = new LinkedList<>();
    private Set<String> resultUrls = new HashSet<>(300);
    private Pattern urlPattern = Pattern.compile("^((https|http)?://)[^\\s]+", Pattern.CASE_INSENSITIVE);
    private PatternMatcher scopeMatcher;

    public FetchContext(PatternMatcher scopePattern) {
        this.scopeMatcher = scopePattern;
    }

    public void dumpStatus() {
        LOGGER.info("已扫描地址数：{}， 待扫描地址数：{}", resultUrls.size(), urlList.size());
    }

    /**
     * 获取url地址匹配正则
     *
     * @return
     */
    public Pattern getUrlPattern() {
        return urlPattern;
    }

    /**
     * 设置新的url地址匹配正则，替换掉默认的正则
     *
     * @param urlPattern
     */
    public void setUrlPattern(Pattern urlPattern) {
        this.urlPattern = urlPattern;
    }

    /**
     * 是否需要获取当前链接对应页面中的子链接URL
     *
     * @return
     */
    public boolean isFetchUrls() {
        return fetchUrls;
    }

    /**
     * 设置获取当前页面链接标识
     *
     * @param fetchUrls
     */
    public void setFetchUrls(boolean fetchUrls) {
        this.fetchUrls = fetchUrls;
    }

    /**
     * 获取当前处理的url
     *
     * @return
     */
    public String getUrl() {
        return url;
    }

    /**
     * 获取当前处理的url
     *
     * @param url
     */
    public void setUrl(String url) {
        this.url = url;
    }

    /**
     * 添加待扫描地址
     *
     * @param url 待添加的地址
     * @return true添加成功， fasle未添加
     */
    public boolean addUrl(String url) {
        try {
            LOCK.lock();
            url = StringUtils.trimToNull(url);

            if (StringUtils.isNotBlank(url)
                    && urlPattern.matcher(url).matches()
                    && scopeMatcher.matches(url)) {
                if (!urlList.contains(url) && !resultUrls.contains(url)) {
                    LOGGER.debug("添加待扫描URL {}", url);
                    urlList.add(url);
                    return true;
                }
            } else {
                if (PatternUtil.isHttpUrl(url)) {
                    String domain = PatternUtil.getUrlDomain(url);
                    if (StringUtils.isNotBlank(domain)) {
                        LOGGER.error("未处理的域名:{} 地址:{}", domain, url);
                    }
                }
            }

            return false;
        } finally {
            LOCK.unlock();
        }
    }

    /**
     * 获取下一个可扫描地址，如果没有返回null
     *
     * @return
     */
    public String getNextUrl() {
        try {
            LOCK.lock();
            if (urlList.size() > 0) {
                return urlList.poll();
            }
            return null;
        } finally {
            LOCK.unlock();
        }
    }
}
